package com.ruijie.acl.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.springframework.util.Assert;

import com.ruijie.acl.AccessGroup;
import com.ruijie.acl.AclDevice;
import com.ruijie.acl.AclInterface;
import com.ruijie.acl.AclInterfaceView;
import com.ruijie.acl.AclPlanInterface;
import com.ruijie.acl.task.config.TaskConfigAclDevice;
import com.ruijie.acl.task.model.AclInterfaceInfo;
import com.ruijie.acl.utils.AclConfigUtil;
import com.ruijie.acl.utils.AclUtil;
import com.ruijie.batch.plan.PlanParameters;
import com.ruijie.emp.device.Device;
import com.ruijie.emp.device.DeviceInterface;
import com.ruijie.foundation.dao.support.Page;
import com.ruijie.foundation.utils.StringUtils;

public class AclInterfaceServiceImpl extends AclHibernateEntityExtendDao<AclInterface> implements AclInterfaceService {
	
	private AceService aceService;

	private TaskConfigAclDevice taskConfigAclDevice;
	
	private AccessGroupService accessGroupService;
	

	@Override
	public Page pageQueryByDevice(Device device, int pageNo, int pageSize) {
		Assert.notNull(device);
		Criteria criteria = createCriteria(AclInterfaceView.class);
		criteria.add(Restrictions.eq("device", device));
		criteria.addOrder(org.hibernate.criterion.Order.asc("ifIndex"));
		return pagedQuery(criteria, pageNo, pageSize);
	}
	
	/**
	 * 根据设备获取接口信息
	 * 
	 * @param device
	 * @return List
	 */
	public List<AclInterface> getListByDevice(Device device) {
		Assert.notNull(device);
		
		List<AclInterface> list = findBy("device", device);
		
		return list;
	}
	
	/**
	 * 通过aclInterfaces获得acl组
	 * @param aclInterfaces
	 * @return
	 */
	public List<AccessGroup> getAccessGroups(List<AclInterface> aclInterfaces){
		List<AccessGroup> accessGroups = new ArrayList<AccessGroup>();
		for(AclInterface aclInterface:aclInterfaces){
			if(aclInterface.getInAccessGroup()!=null){
				accessGroups.add(aclInterface.getInAccessGroup());
			}
			if(aclInterface.getOutAccessGroup()!=null){
				accessGroups.add(aclInterface.getOutAccessGroup());
			}
		}
		HashSet<AccessGroup> hashSet = new HashSet<AccessGroup>(accessGroups);
		accessGroups.clear();
		accessGroups.addAll(hashSet);
		return accessGroups;
	}
	
	
	/**
	 * 根据设备和ACL组取得ACL接口视图分页信息
	 * @param device 设备
	 * @param accessGroup ACL组
	 * @param pageNo 页数
	 * @param pageSize 页尺寸
	 * @return ACL接口视图分页信息
	 */
	public Page pageQueryByDeviceAndAccessGroup(Device device, AccessGroup accessGroup, int pageNo, int pageSize){
		Assert.notNull(device);
		Assert.notNull(accessGroup);
		Criteria criteria = createCriteria(AclInterfaceView.class);
		criteria.add(Restrictions.eq("device", device));
		criteria.add(Restrictions.or(
				Restrictions.eq("inAccessGroup", accessGroup), 
				Restrictions.eq("outAccessGroup", accessGroup))
				);
		criteria.addOrder(org.hibernate.criterion.Order.asc("ifIndex"));
		return pagedQuery(criteria, pageNo, pageSize);
	}
	
	/**
	 * 通过device和accessGroup获得AclInterface
	 * @param device
	 * @param accessGroup
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<AclInterface> getAclInterfaces(Device device, AccessGroup accessGroup){
		Assert.notNull(device);
		Assert.notNull(accessGroup);
		Criteria criteria = createCriteria(AclInterface.class);
		criteria.add(Restrictions.eq("device", device));
		criteria.add(Restrictions.or(
				Restrictions.eq("inAccessGroup", accessGroup), 
				Restrictions.eq("outAccessGroup", accessGroup))
				);
		List<AclInterface> aclInterfaces =  criteria.list();
		/*循环判断如果aclInterface中的组不等于当前的组就置空*/
		for(AclInterface aclInterface:aclInterfaces){
			if(!accessGroup.getName().equals(aclInterface.getOutAccessGroupName())){
				aclInterface.setOutAccessGroup(null);
				aclInterface.setOutAccessGroupName(null);
			}
			if(!accessGroup.getName().equals(aclInterface.getInAccessGroupName())){
				aclInterface.setInAccessGroup(null);
				aclInterface.setInAccessGroupName(null);
			}
		}
		return aclInterfaces;
	}

	/**
	 * 根据设备和组，选择出部署了此组的AclPlanInterface
	 * @param device
	 * @param accessGroup
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<AclPlanInterface> getAclPlanInterfaces(Device device,List<AccessGroup> accessGroups){
		Assert.notNull(device);
		Assert.notNull(accessGroups);
		Criteria criteria = createCriteria(AclInterface.class);
		criteria.add(Restrictions.eq("device", device));
		for(AccessGroup accessGroup:accessGroups){
			criteria.add(Restrictions.or(
					Restrictions.eq("inAccessGroup", accessGroup), 
					Restrictions.eq("outAccessGroup", accessGroup))
					);
		}
		List<AclInterface> aclInterfaces =  criteria.list();
		List<AclPlanInterface> aclPlanInterfaces=null;
		if(aclInterfaces!=null){
			aclPlanInterfaces=new ArrayList<AclPlanInterface>();
			AclDevice aclDevice=this.getAclDevice(device);
			for(AclInterface aclInterface:aclInterfaces){
				if(accessGroups.indexOf(aclInterface.getInAccessGroup())<0){
					aclInterface.setInAccessGroup(null);
				}
				if(accessGroups.indexOf(aclInterface.getOutAccessGroup())<0){
					aclInterface.setOutAccessGroup(null);
				}
				AclPlanInterface aclPlanInterface=new AclPlanInterface();
				aclPlanInterface.setDeviceInterface(aclInterface.getDeviceInterface());
				aclPlanInterface.setInAccessGroup(aclInterface.getInAccessGroup());
				aclPlanInterface.setOutAccessGroup(aclInterface.getOutAccessGroup());
				aclPlanInterface.setAclDevice(aclDevice);
				aclPlanInterfaces.add(aclPlanInterface);
			}
		}
		return aclPlanInterfaces;
	}

	
	/**
	 * 根据设备取得ACL设备
	 * @param device 设备
	 * @return ACL设备
	 */
	@SuppressWarnings("unchecked")
	private AclDevice getAclDevice(Device device){
		Assert.notNull(device);
		AclDevice aclDevice = null;
		Criteria criteria = createCriteria(AclDevice.class);
		criteria.add(Restrictions.eq("device", device));
		List<AclDevice> list = (List<AclDevice>)criteria.list();
		if (list != null && list.size() > 0){
			aclDevice = list.get(0);
		}
		return aclDevice;
	}
	
	/**
	 * 根据设备取得设备接口
	 * 
	 * @param device
	 *            设备
	 * @return 设备接口列表
	 */
	@SuppressWarnings("unchecked")
	public List<AclInterfaceView> getAclInterfaceViewByDevice(Device device) {
		Assert.notNull(device);
		Criteria criteria = createCriteria(AclInterfaceView.class);
		Criterion parentCriterion = Restrictions.eq("device", device);
		criteria.add(parentCriterion);
		//criteria.addOrder(Order.asc("name"));
		List<AclInterfaceView> list = criteria.list();
		//return InterfaceSortUtil.sortInterfaceItemList(list);
		return list;
	}
	
	/**
	 * 根据id取得设备接口
	 * 
	 * @param device
	 *            设备
	 * @return 设备接口列表
	 */
	@SuppressWarnings("unchecked")
	public AclInterfaceView getAclInterfaceViewById(Long interfaceId) {
		Assert.notNull(interfaceId);
		Criteria criteria = createCriteria(AclInterfaceView.class);
		Criterion parentCriterion = Restrictions.eq("id", interfaceId);
		criteria.add(parentCriterion);
		//criteria.addOrder(Order.asc("name"));
		AclInterfaceView aclInterfaceView = (AclInterfaceView)criteria.uniqueResult();
		//return InterfaceSortUtil.sortInterfaceItemList(list);
		return aclInterfaceView;
	}
	
	/**
	 * 根据接口ID，取得接口信息
	 * @param id 接口ID
	 * @return 接口信息
	 */
	public DeviceInterface getDeviceInterface(Long id){
		Assert.notNull(id);
		return this.get(DeviceInterface.class, id);
	}
	
	/**
	 * 根据设备接口ID，取得ACL接口信息
	 * @param id 接口ID
	 * @return 接口信息
	 */
	public AclInterface getAclInterfaceByDeviceInterface(Long deviceInterfaceId){
		String hql = "from AclInterface where deviceInterface.id=?";
		return (AclInterface)createQuery(hql, deviceInterfaceId).uniqueResult();
	}
	
	/**
	 * 根据ID，取得ACL组信息
	 * 用于部署时使用
	 * @param id ID
	 * @return ACL组信息
	 */
	public AccessGroup getAccessGroup(Long id){
		Assert.notNull(id);
		AccessGroup accessGroup = null;
		try{
			accessGroup = this.get(AccessGroup.class, id);
		}catch(Exception ex){
			// 
		}
		return accessGroup;
	}
	
	/**
	 * 根据设备取得设备接口列表
	 * @param device 设备
	 * @return 设备接口列表
	 */
	public List<DeviceInterface> getInterfaceByDevice(Device device){
		Assert.notNull(device);
		Assert.notNull(device.getId());
		List<DeviceInterface> list = new ArrayList<DeviceInterface>();
		Device entity = this.get(Device.class, device.getId());
		Set<DeviceInterface> interfaces = entity.getInterfaces();
		if (interfaces != null && interfaces.size() > 0){
			for (DeviceInterface deviceInterface : interfaces){
				list.add(deviceInterface);
			}
		}
		return list;
	}
	
	/**
	 * 根据设备和接口取得ACL设备
	 * @param device 设备
	 * @param deviceInterface 接口
	 * @return ACL设备
	 */
	@SuppressWarnings("unchecked")
	public AclInterface getByDeviceAndInterface(Device device, DeviceInterface deviceInterface){
		Assert.notNull(device);
		Assert.notNull(deviceInterface);
		AclInterface result = null;
		Criteria criteria = createCriteria(AclInterface.class);
		criteria.add(Restrictions.eq("device", device));
		criteria.add(Restrictions.eq("deviceInterface", deviceInterface));
		List<AclInterface> list = (List<AclInterface>)criteria.list();
		if (list != null && list.size() > 0){
			result = list.get(0);
		}
		return result;
	}
	/**
	 * 根据ACL组取得ACL接口列表
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<AclInterface> findByAccessGroup(List<AccessGroup> accessGroupList){
		Assert.notEmpty(accessGroupList);
		Criteria criteria = createCriteria(AclInterface.class);
		criteria.add(Restrictions.or(Restrictions.in("outAccessGroup",accessGroupList), 
				Restrictions.in("inAccessGroup",accessGroupList)));
		return criteria.list();
	}
	
	/**
	 * 根据ACL组ID列表更新接口配置
	 * @param ids ID列表
	 */
	public void updateInterfaceByAccessGroupIds(String ids){
		Assert.notNull(ids);
		String hql = "update AclInterface set inAccessGroupName = null ,inAccessGroup = null " +
				"where inAccessGroup.id in (" + ids + ") ";
		this.createQuery(hql).executeUpdate();
		hql = "update AclInterface set outAccessGroupName = null,outAccessGroup = null " + 
				"where outAccessGroup.id in (" + ids + ") ";
		this.createQuery(hql).executeUpdate();
	}
		
	/**
	 * 通过DeviceInterface删除AclInterfalce
	 * @param entity
	 */
	public void removeAclInterfalceByDeviceInterface(Long aclinterfaceId,Long id,String InorOut){
		Assert.notNull(id);
		AclInterface aclInterface = get(aclinterfaceId);
		String inputGroupName = aclInterface.getInAccessGroupName();
		String outputGroupName =  aclInterface.getOutAccessGroupName();
		String hql = "";
		if(!StringUtils.isNullOrEmpty(inputGroupName)&&!StringUtils.isNullOrEmpty(outputGroupName)){
			if("In".equals(InorOut)){
				hql = "update AclInterface set inAccessGroup = null ,inAccessGroupName = null " +
				"where deviceInterface.id=?";
			}else{
				hql = "update AclInterface set outAccessGroup = null ,outAccessGroupName = null " +
				"where deviceInterface.id=?";
			}
		}else{
			hql = "delete AclInterface where deviceInterface.id=?";
		}
		
		createQuery(hql, id).executeUpdate();
	}
	
	/**
	 * 部署ACL组到接口
	 * @param id
	 * @param device
	 */
	public void reConfig(AclInterfaceView interfaceView,Device device,String InorOut,String flag){
		PlanParameters parameters = new PlanParameters();
		
		/*存入accessGroupInfoList*/
		List<AclInterfaceInfo> interfaceInfoList = AclConfigUtil.getInterfaceInfos(interfaceView,InorOut);
		parameters.putParameter("aclInterfaceInfoList", interfaceInfoList);
		
		/*存入DealType*/
		parameters.putParameter("dealFlag",flag);
		taskConfigAclDevice.processItem(device, parameters);
	}
	
	
	/**
	 * 批量部署接口
	 * @param id
	 * @param device
	 */
	public void reConfigSelectInterface(Device device,List<AccessGroup> accessGroups,String selectedInterfaceByAccessGroup){
			PlanParameters parametersAdd = new PlanParameters();
			PlanParameters parametersDel = new PlanParameters();

			/*获得存入的accessGroupInfoList*/
			List<AclInterfaceInfo> interfaceInfoListNew = convertString2AclInterfaceInfo(selectedInterfaceByAccessGroup);
			
			/*获得要删除的aclInterfaceList*/
			List<AclInterface> aclInterfaceListOld = getListByDevice(device);
			List<AclInterfaceInfo> interfaceInfoListOld = AclConfigUtil.aclInterface2AclInterfaceInfoList(aclInterfaceListOld);
			
			if(interfaceInfoListOld.size()>0){
				parametersDel.putParameter("aclInterfaceInfoList", interfaceInfoListOld);
				parametersDel.putParameter("dealFlag","delete");
				taskConfigAclDevice.processItem(device, parametersDel);
			}
			if(interfaceInfoListNew.size()>0){
				parametersAdd.putParameter("aclInterfaceInfoList", interfaceInfoListNew);
				parametersAdd.putParameter("dealFlag","add");
				taskConfigAclDevice.processItem(device, parametersAdd);
			}
	}
	
	/**
	 * 把字符串转换成接口类型
	 * @param planInterfaceString 
	 * @return
	 */
	public List<AclInterfaceInfo> convertString2AclInterfaceInfo(String planInterfaceString) {
		List<AclInterfaceInfo> aclPlanInterfaceList = null;
		if (!AclUtil.empty(planInterfaceString)) {
			aclPlanInterfaceList = new ArrayList<AclInterfaceInfo>();
			String[] arrAclInterfaceList = planInterfaceString.split(";");
			for (String interfaceStr : arrAclInterfaceList) {
				AclInterfaceInfo interfaceInfo = new AclInterfaceInfo();
				String[] arrAclInterfaces = interfaceStr.split(",");
				String intPutName = "";
				String outPutName = "";
				if (arrAclInterfaces.length == 3) {
					//当组Id为-1时，表示组在设备中不存在
					if(arrAclInterfaces[2].equals("-1")){
						AclInterface interfaceNoGroup = getAclInterfaceByDeviceInterface(Long.valueOf(arrAclInterfaces[0]));
						intPutName = interfaceNoGroup.getInAccessGroupName();
						outPutName = interfaceNoGroup.getOutAccessGroupName();
					}else{
						AccessGroup accessGroup = accessGroupService.get(Long.valueOf(arrAclInterfaces[2]));
						intPutName = accessGroup.getName();
						outPutName = accessGroup.getName();
					}
					String type = arrAclInterfaces[1];
					interfaceInfo.setIfName(getAclInterfaceViewById(Long.valueOf(arrAclInterfaces[0])).getName());
					if("InOut".equals(type)){
						interfaceInfo.setInAccessGroupName(intPutName);
						interfaceInfo.setOutAccessGroupName(outPutName);
					}else if("In".equals(type)){
						interfaceInfo.setInAccessGroupName(intPutName);
					}else{
						interfaceInfo.setOutAccessGroupName(outPutName);
					}
				}
				aclPlanInterfaceList.add(interfaceInfo);
			}
		}
		return aclPlanInterfaceList;
	}
	
	
	/**
	 * 根据设备删除ACL接口
	 * @param entity 设备
	 */
	public void removeByDevice(Device entity){
		Assert.notNull(entity);
		String hql = "delete from AclInterface where device = ?";
		this.createQuery(hql, entity).executeUpdate();
	}
	
	/**
	 * 添加Acl Interface列表 
	 * @param aclInterfaceInfoList Acl Interface列表
	 */
	public void addAclInterfaces(List<AclInterfaceInfo> aclInterfaceInfoList,Device device){
		Assert.notNull(device);
		if (aclInterfaceInfoList != null && aclInterfaceInfoList.size() > 0){
			//遍历AclInterfaceInfo处理
			List<DeviceInterface> deviceInterfaceList = this.getInterfaceByDevice(device);
			for(AclInterfaceInfo aclInterfaceInfo : aclInterfaceInfoList){
				AclInterface entity = null;
				List<AclInterface> aclInterfaceList = this.getListByDevice(device);
				for(AclInterface aclInterface : aclInterfaceList){
					if (aclInterface.getDeviceInterface().getName().equals(aclInterfaceInfo.getIfName())){
						entity = aclInterface;
						break;
					}
				}
				
				// 新增
				if (entity == null){
					entity = new AclInterface();
					//根据ifname名称取得DeviceInterface信息进行设置
					for (DeviceInterface deviceInterface : deviceInterfaceList){
						if (aclInterfaceInfo.getIfName().equals(deviceInterface.getName())){
							entity.setDeviceInterface(deviceInterface);
							break;
						}
					}
				}
				
				//根据outAccessGroup名称取得AccessGroup信息进行设置
				if (aclInterfaceInfo.getOutAccessGroupName()!= null){
					entity.setOutAccessGroupName(aclInterfaceInfo.getOutAccessGroupName());
					entity.setOutAccessGroup(accessGroupService.getByNameWithoutAclDevice(aclInterfaceInfo.getOutAccessGroupName()));
				}
				//根据inAccessGroup名称取得AccessGroup信息进行设置
				if (aclInterfaceInfo.getInAccessGroupName() != null){
					entity.setInAccessGroupName(aclInterfaceInfo.getInAccessGroupName());
					entity.setInAccessGroup(accessGroupService.getByNameWithoutAclDevice(aclInterfaceInfo.getInAccessGroupName()));
				}
				
				//设置Device
				entity.setDevice(device);
				
				this.save(entity);
				
			}
		}
	}
	
	/**
	 * 根据设备和选择的接口，找出需要删除的接口部署信息
	 * @return 封装了in和out组的AclInterfaceInfo
	 */	
	public Map<String,AclInterfaceInfo> getAclInterfaceInfoMapByDevice(Device device,List<AclInterfaceInfo> ifInfoList){
		Assert.notNull(device);
		Assert.notNull(ifInfoList);
		Criteria criteria = createCriteria(AclInterface.class);
		criteria.add(Restrictions.eq("device", device));
		List result=criteria.list();
		if(result!=null&&result.size()>0){
			//传进来新的接口信息，封装到一个Map中，用于查找
			Map<String,AclInterfaceInfo> ifInfoMap=new HashMap<String,AclInterfaceInfo>();
			for(AclInterfaceInfo ifInfo:ifInfoList){
				ifInfoMap.put(ifInfo.getIfName(), ifInfo);
			}
			Map<String,AclInterfaceInfo> deleteIfInfoMap=new HashMap<String,AclInterfaceInfo>();
			//对旧的接口进行遍历
			for(Object obj:result){
				//旧的部署接口信息
				AclInterface aclInterface=(AclInterface)obj;
				
				String ifName=aclInterface.getDeviceInterface().getName();
				AclInterfaceInfo aclInterfaceInfo=ifInfoMap.get(ifName);
				if(aclInterfaceInfo!=null){
					AclInterfaceInfo deleteIfInfo=null;
					String newIn=aclInterfaceInfo.getInAccessGroupName();	//旧的接口In方向部署的组
					String newOut=aclInterfaceInfo.getOutAccessGroupName();	//旧的接口Out方向部署的组
					String oldIn=aclInterface.getInAccessGroupName();	//新的接口In方向部署的组
					String oldOut=aclInterface.getOutAccessGroupName();	//新的接口Out方向部署的组
					if(oldIn!=null&&newIn!=null&&!oldIn.equals(newIn)){
						//新的接口部署覆盖旧的接口部署
						if(deleteIfInfo==null){
							deleteIfInfo=new AclInterfaceInfo();
							deleteIfInfo.setIfName(ifName);							
						}
						deleteIfInfo.setInAccessGroupName(oldIn);
					}
					if(oldOut!=null&&newOut!=null&&!oldOut.equals(newOut)){
						//新的接口部署覆盖旧的接口部署
						if(deleteIfInfo==null){
							deleteIfInfo=new AclInterfaceInfo();
							deleteIfInfo.setIfName(ifName);							
						}
						deleteIfInfo.setOutAccessGroupName(oldOut);
					}
					//新旧重复，需进行判断
					if(deleteIfInfo!=null){
						deleteIfInfoMap.put(ifName, deleteIfInfo);
					}
				}
			}
			return deleteIfInfoMap;
		}
		return null;
	}
	
	public AceService getAceService() {
		return aceService;
	}

	public void setAceService(AceService aceService) {
		this.aceService = aceService;
	}

	public TaskConfigAclDevice getTaskConfigAclDevice() {
		return taskConfigAclDevice;
	}

	public void setTaskConfigAclDevice(TaskConfigAclDevice taskConfigAclDevice) {
		this.taskConfigAclDevice = taskConfigAclDevice;
	}

	public AccessGroupService getAccessGroupService() {
		return accessGroupService;
	}

	public void setAccessGroupService(AccessGroupService accessGroupService) {
		this.accessGroupService = accessGroupService;
	}
}
